在 MongoDB 當中,有著每個 Document 的大小最大為 16 MB 的限制,如果今天你想插入的資料超過 16 MB,MonGODB 提供了 GridFS API 來協助你內容進行切割,同時他也可以針對各種檔案進行儲存,今天會分別使用存入 json 格式以及儲存圖片的方式帶大家了解 GridFS 的操作
JSON 格式是我們最常用來存放在 mongodb 裡面的資料格式,但 GridFS 只接收字串以及檔案類型的參數,因此在寫入 JSON 或是 dictionary 等型態的資料時,我們必須先透過 json 套件將資料轉換成字串,接著再寫入,下方附上範例
import os
import json
from pathlib import Path
from dotenv import load_dotenv
from pymongo.database import Database
from gridfs import GridFS
from pymongo.mongo_client import MongoClient
# 讀取 .env 取得連線資訊
BASE_DIR = Path(__file__).parent.parent
load_dotenv(str(BASE_DIR / ".env"))
# 讀取 datas 目錄下的 1 月份資料
file = BASE_DIR / "datas" / "臺中市111年1月10大易肇事路口.json"
# 設定連線資訊
# 建立 client 並與 db 進行連線
client = MongoClient(host=os.getenv("MONGODB_ATLAS_URL"))
database = Database(client=client, name="2023_ithelp")
# 建立 GridFS 物件
gridfs = GridFS(database=database)
with open(file=file, encoding="utf-8") as f:
# 讀取 json 檔案的內容
datas = json.load(fp=f)
# 將 dictionary 轉換成字串,並指定字串編碼
string_datas = json.dumps(datas).encode("utf-8")
# 進行寫入
inserted_id = gridfs.put(data=string_datas)
print(inserted_id)
client.close()
下方圖片中我們可以看到成功插入後印出的 inserted_id
下方圖片中午們可以透過 Mongo Compass 看到 GridFS 自動幫我們建立了兩個 collection
我們可以透過 GridFS.get() 並搭配 id 來取得被切割的檔案,由於檔案經過切割,需要使用檔案的時候要將回傳的資料透過迴圈進行跌代重組才可以進行使用
GridFS 會協助將存放的內容已 binary 的形式進行切割,因此若存放的資料為字串讀回來時須作相對應的 decode 動作
import os
import json
from pathlib import Path
from dotenv import load_dotenv
from pymongo.database import Database
from gridfs import GridFS
from pymongo.mongo_client import MongoClient
from bson.objectid import ObjectId
# 讀取 .env 取得連線資訊
BASE_DIR = Path(__file__).parent.parent
load_dotenv(str(BASE_DIR / ".env"))
# 建立 client 並與 db 進行連線
client = MongoClient(host=os.getenv("MONGODB_ATLAS_URL"))
database = Database(client=client, name="2023_ithelp")
# 建立 GridFS 物件
gridfs = GridFS(database=database)
# 透過 id 取得所有被切割的檔案,記得 id 要使用 bson.object_id.ObjectId
chunks = gridfs.get(file_id=ObjectId("646389db4f978885e6985b93"))
# 將 chunks 進行重組
result = b""
for chunk in chunks:
result += chunk
print(json.loads(result.decode("utf8")))
client.close()
下圖為查詢成功範例
基本上和 json 格式寫入的方式相差不大,但要注意的是開啟檔案的時候要記得使用 "rb" 模式,也就是 read binary 的意思
import os
from pathlib import Path
from dotenv import load_dotenv
from pymongo.database import Database
from gridfs import GridFS
from pymongo.mongo_client import MongoClient
# 讀取 .env 取得連線資訊
BASE_DIR = Path(__file__).parent.parent
load_dotenv(str(BASE_DIR / ".env"))
# 建立 client 並與 db 進行連線
client = MongoClient(host=os.getenv("MONGODB_ATLAS_URL"))
database = Database(client=client, name="2023_ithelp")
# 建立 GridFS 物件
gridfs = GridFS(database=database)
with open(file="範例圖片.png", mode="rb") as file:
inserted_id = gridfs.put(data=file)
print(inserted_id)
client.close()
下圖為插入檔案成功截圖
同樣的,這邊也需要使用 "wb" 來表示要進行 write binary 的動作,同時賦予新的檔案新的名稱
注意:若要存放檔案必須有一個對應的 collection 來存放檔案名稱、副檔名以及插入後所產生的 id,此為最理想的應用情況
import os
from pathlib import Path
from dotenv import load_dotenv
from pymongo.database import Database
from gridfs import GridFS
from pymongo.mongo_client import MongoClient
from bson.objectid import ObjectId
# 讀取 .env 取得連線資訊
BASE_DIR = Path(__file__).parent.parent
load_dotenv(str(BASE_DIR / ".env"))
# 建立 client 並與 db 進行連線
client = MongoClient(host=os.getenv("MONGODB_ATLAS_URL"))
database = Database(client=client, name="2023_ithelp")
# 建立 GridFS 物件
gridfs = GridFS(database=database)
# 透過 id 取得所有被切割的檔案,記得 id 要使用 bson.object_id.ObjectId
chunks = gridfs.get(file_id=ObjectId("64638f1de59d60a299db3c72"))
# 將 chunks 進行重組
result = b""
for chunk in chunks:
result += chunk
with open("讀取後的圖片.png", "wb") as file:
file.write(result)
client.close()
下圖為讀取檔案並寫入成功的截圖